package org.domon.mybatis.sql.support;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.jdbc.SQL;
import org.domon.mybatis.bind.ModelRegistry;
import org.domon.mybatis.exception.NoSuchColumnException;
import org.domon.mybatis.sql.DbNameGenerator;
import org.springframework.util.StringUtils;

public class DefaultDbNameGenerator implements DbNameGenerator {

    protected final Log logger = LogFactory.getLog(getClass());

    @Override
    public void initializeAllSQL(Class<?> beanClass, ModelRegistry modelRegistry) {
        modelRegistry.addTableName(beanClass, this.getDbName(beanClass.getSimpleName()));
        modelRegistry.addTableKey(beanClass, this.getTableKey(beanClass).getName());
        
        modelRegistry.addEqualsSql(beanClass, this.generateEqualsSql(beanClass));

        modelRegistry.addInsertSql(beanClass, this.generateInsertSql(beanClass, modelRegistry));
        modelRegistry.addDeleteSql(beanClass, this.generateDeleteSql(beanClass, modelRegistry));
    }

    /**
     * 初始化插入sql
     * 
     * @param insertSqlMap
     * @param beanClass
     */
    protected String generateInsertSql(Class<?> beanClass, ModelRegistry modelRegistry) {
        SQL BUILD = new SQL();
        BUILD.INSERT_INTO(modelRegistry.getTableName(beanClass));

        Field[] fields = beanClass.getDeclaredFields();
        for (Field field : fields) {
            BUILD.VALUES(getDbName(field.getName()), DB_VALUE.replace("?", field.getName()));
        }
        return BUILD.toString();
    }

    /**
     * 初始化删除sql
     * 
     * @param deleteSqlMap
     * @param beanClass
     */
    protected String generateDeleteSql(Class<?> beanClass, ModelRegistry modelRegistry) {
        SQL BUILD = new SQL();
        BUILD.DELETE_FROM(modelRegistry.getTableName(beanClass));
        BUILD.WHERE(getDbEqualsSql(modelRegistry.getTableKey(beanClass)));
        return BUILD.toString();
    }

    /**
     * 初始化条件sql
     * 
     * @param equalsSqlMap
     * @param beanClass
     */
    protected Map<String, String> generateEqualsSql(Class<?> beanClass) {
        Map<String, String> equalsSql = new HashMap<String, String>();

        Field[] fields = beanClass.getDeclaredFields();
        for (Field field : fields) {
            equalsSql.put(field.getName(), getDbEqualsSql(field.getName()));
        }
        return equalsSql;
    }
    
    protected String getDbEqualsSql(String fieldName) {
        StringBuffer buffer = new StringBuffer(fieldName.length() * 2);
        buffer.append(getDbName(fieldName));
        buffer.append("=");
        buffer.append(DB_VALUE.replace("?", fieldName));
        return buffer.toString();
    }

    /**
     * 根据java属性名获取数据库字段名
     * eg: TrMerchantOrder --> TR_MERCHANT_ORDER
     * 
     * @param javaName
     * @return
     */
    protected String getDbName(String javaName) {
        if (StringUtils.isEmpty(javaName)) {
            return "";
        }
        StringBuffer buffer = new StringBuffer(javaName);

        char[] ch = javaName.toCharArray();
        int index = 0;
        for (int i = 1; i < ch.length; i++) {
            if (Character.isUpperCase(ch[i])) {
                buffer.insert(i + (index++), UNDER_LINE);
            }
        }
        return buffer.toString().toUpperCase();
    }

    /**
     * 获取DB table的主键
     * 
     * @param beanClass
     * @return
     */
    protected Field getTableKey(Class<?> beanClass) {
        Field[] fields = beanClass.getDeclaredFields();
        for (Field field : fields) {
            if (isTableKey(field)) {
                return field;
            }
        }

        throw new NoSuchColumnException(getDbName(beanClass.getSimpleName()), "id");
    }

    /**
     * 判断字段是不是主键
     * 
     * @param field
     * @return
     */
    protected boolean isTableKey(Field field) {
        if (StringUtils.isEmpty(field.getName())) {
            return false;
        }
        if (StringUtils.endsWithIgnoreCase(field.getName(), "id")) {
            return true;
        }
        return false;
    }

    @Override
    public String generateUpdateSql(ModelRegistry modelRegistry, Class<?> beanClass, String[] fieldNames) {
        SQL BUILD = new SQL();
        BUILD.UPDATE(modelRegistry.getTableName(beanClass));
        for (int i = 0; i < fieldNames.length; i++) {
            if (StringUtils.isEmpty(modelRegistry.getEqualsSql(beanClass, fieldNames[i]))) {
                throw new NoSuchColumnException(modelRegistry.getTableName(beanClass), fieldNames[i]);
            }
            BUILD.SET(modelRegistry.getEqualsSql(beanClass, fieldNames[i]));
        }
        BUILD.WHERE(getDbEqualsSql(modelRegistry.getTableKey(beanClass)));
        return BUILD.toString();
    }

}
